#ifndef TONGLUN_H
#define TONGLUN_H

#ifdef __cplusplus
#include <cstdint>
#include <cstddef>
extern "C" {
#else
#include <stdint.h>
#include <stddef.h>
#endif

struct TLValue {
  uint8_t tag;
  uint64_t _data;
};

typedef uint64_t TLError;

enum TLValueTag {
  TL_VALUE_TAG_NONE = 1,
  TL_VALUE_TAG_BOOL = 2,
  TL_VALUE_TAG_INT64 = 3,
  TL_VALUE_TAG_FLOAT64 = 4,
  TL_VALUE_TAG_COMPLEX32 = 5,
  TL_VALUE_TAG_COMPLEX64 = 6,
  TL_VALUE_TAG_STRING = 7,
  TL_VALUE_TAG_ARRAY = 8,
  TL_VALUE_TAG_HLIST = 9,
};

enum TLArrayDType {
  TL_DTYPE_BOOL = 0,
  TL_DTYPE_INT8 = 1,
  TL_DTYPE_INT16 = 2,
  TL_DTYPE_INT32 = 3,
  TL_DTYPE_INT64 = 4,
  TL_DTYPE_UINT8 = 5,
  TL_DTYPE_UINT16 = 6,
  TL_DTYPE_UINT32 = 7,
  TL_DTYPE_UINT64 = 8,
  TL_DTYPE_FLOAT32 = 9,
  TL_DTYPE_FLOAT64 = 10,
  TL_DTYPE_COMPLEX32 = 11,
  TL_DTYPE_COMPLEX64 = 12,
};

// Runtime management
TLError tonglun_create_runtime(
    // [OUT]
    uint32_t *runtime_id,

    // [IN]
    void *dlhandle, char *name, uint8_t thread_safe,
    void (*string_drop_callback)(void *foreign_ob),
    void (*array_drop_callback)(void *foreign_ob));

TLError tonglun_run_deferred_free(uint32_t runtime_id);

// Value management
TLError tonglun_free_value(
    // [IN]
    const struct TLValue *value);

// Value creation
TLError tonglun_create_none(
    // [OUT]
    struct TLValue *out);

TLError tonglun_create_bool(
    // [OUT]
    struct TLValue *out, uint8_t value);

TLError tonglun_create_int64(
    // [OUT]
    struct TLValue *out, int64_t value);

TLError tonglun_create_float64(
    // [OUT]
    struct TLValue *out, double value);

TLError tonglun_create_complex32(
    // [OUT]
    struct TLValue *out, float real, float imag);

TLError tonglun_create_complex64(
    // [OUT]
    struct TLValue *out, double real, double imag);

TLError tonglun_create_string_copied(
    // [OUT]
    struct TLValue *out, char *input);

TLError tonglun_create_string_borrowed(
    // [OUT]
    struct TLValue *out,

    // [IN]
    uint32_t runtime_id, char *input, void *foreign_ob);

TLError tonglun_create_array(
    // [OUT]
    struct TLValue *out,

    // [IN]
    uint32_t runtime_id,
    // b8, b16, b32, b64, u8, u16, u32, u64, f32, f64, c32, c64
    char *typecode, void *data, uint64_t ndims, uint64_t *dimensions,
    int64_t *strides, void *foreign_ob, uint8_t readonly, uint8_t fortran_order);

TLError tonglun_create_tuple(
    // [OUT]
    struct TLValue *out,

    // [IN]
    uint64_t nitems, const struct TLValue *items);

// Value access functions
enum TLValueTag tonglun_value_tag(const struct TLValue *value);

uint8_t tonglun_get_bool(const struct TLValue *value);
int64_t tonglun_get_int64(const struct TLValue *value);
double tonglun_get_float64(const struct TLValue *value);

// LOAD API - loads data into provided pointers
void tonglun_load_string(char **out, const struct TLValue *value);
void tonglun_load_complex32(float *real, float *imag, const struct TLValue *value);
void tonglun_load_complex64(double *real, double *imag, const struct TLValue *value);

// Array access
void tonglun_load_array_info(
    // [OUT]
    void **data,
    size_t **dimensions,
    intptr_t **strides,
    int64_t *ndims,
    enum TLArrayDType *dtype,
    uint8_t *readonly,
    uint8_t *fortran_order,
    // [IN]
    uint64_t handle);

// Tuple access
uint64_t tonglun_get_tuple_length(const struct TLValue *tuple);

// 先通过 tonglun_get_tuple_length 获取长度，再通过 tonglun_take_tuple
// 获取每个元素的所有权；此操作将释放 tuple
void tonglun_take_tuple(
    // [OUT]
    struct TLValue *out,

    // [IN]
    const struct TLValue *tuple);

// Function management - UPDATED: now includes data parameter
TLError tonglun_register_function(
    uint32_t runtime_id,
    // [IN]
    char *name,
    // Updated function signature with data parameter
    uint64_t (*fptr)(uint64_t data, struct TLValue *out, const struct TLValue *args, uint64_t nargs),
    uint64_t data);

TLError tonglun_call_function(
    // [OUT]
    struct TLValue *out,

    // [IN]
    char *name, const struct TLValue *args, uint64_t nargs);

// Error handling
TLError tonglun_try_load_error_message(
    // [OUT]
    char *buffer,

    // [IN]
    uint64_t buffer_len_minus_1, TLError error_handle);

uint64_t tonglun_error_buflen(TLError error_handle);

TLError tonglun_free_error(TLError error_handle);

TLError tonglun_binding_error(char *language, char *message);

#ifdef __cplusplus
}
#endif

#endif // TONGLUN_H